package com.lj.demo.springbootshirojwt.service.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.lj.demo.springbootshirojwt.dao.UserMapper;
import com.lj.demo.springbootshirojwt.entity.User;
import com.lj.demo.springbootshirojwt.service.IUserService;
import com.lj.demo.springbootshirojwt.util.Constants;
import com.lj.demo.springbootshirojwt.util.HttpRequestUtil;
import com.lj.demo.springbootshirojwt.util.JWTUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.AuthorizationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * Title: 用户service实现类
 * Description:
 * Date: 2019年06月24日 14:29
 *
 * @author lvjie@hiynn.com
 * @version 1.0
 * Significant Modify：
 * Date                  Author                 Content
 * =================================================================
 * 2019年06月24日         lvjie@hiynn.com         创建文件,实现基本功能
 * =================================================================
 */
@Service
public class UserServiceImplByRedis implements IUserService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private HttpServletRequest request;

    /**
     * 根据用户名获取用户信息
     * @param userName 用户名
     * @return
     */
    @Override
    public User getUserByUserName(String userName){
        User user = (User) redisTemplate.opsForValue().get(userName + Constants.REDIS_KEY_USER);
        if (Objects.equals(user,null)){
            user = userMapper.getUserByUserName(userName);
        }
        return user;
    }

    /**
     * 登录流程
     * @param userName 用户名
     * @param password 密码
     * @return token+user
     */
    @Override
    public Map<String, Object> login(String userName, String password) {
        String passwordByUserName = userMapper.getPasswordByUserName(userName);
        if (!Objects.equals(password,passwordByUserName)){
            throw new AuthorizationException("用户名或密码错误");
        }
        User user = userMapper.getUserByUserName(userName);
        //所有角色
        List<String> roles = user.getRoles().stream().map(role -> role.getName()).collect(Collectors.toList());
        //所有权限
        List<String> permissions = Lists.newArrayList();
        user.getRoles().stream().map(role ->
                role.getAuthorizes().stream().map(authorize -> authorize.getName()).collect(Collectors.toList())
        ).forEach(list->
                list.stream().forEach(permission->
                        permissions.add(permission)
                )
        );
        //生成token  并设置失效时间
        String token = JWTUtil.sign(userName,passwordByUserName,Constants.TOKEN_EXPIRE_TIME,roles,permissions);
        //key规则  userName_user_ip
        redisTemplate.opsForValue().set(userName+Constants.REDIS_KEY_TOKEN+"_"+ HttpRequestUtil.getIpAdrress(request)
                ,token,Constants.REDIS_TOKEN_EXPIRE_TIME, TimeUnit.MILLISECONDS);
        Map<String,Object> resultMap = Maps.newHashMapWithExpectedSize(2);
        resultMap.put("user",user);
        resultMap.put(Constants.TOKEN_KEY,token);
        return resultMap;
    }

    /**
     * 登出  登录可访问
     */
    @Override
    public void logout() {
        String token = request.getHeader(Constants.HTTP_HEADER_TOKEN_KEY);
        if (StringUtils.isEmpty(token)){
            throw new com.lj.demo.springbootshirojwt.exception.AuthorizationException("获取token失败");
        }
        //移除redis中的token
        redisTemplate.opsForValue().getOperations().delete(JWTUtil.getUserName(token)
                +Constants.REDIS_KEY_TOKEN+"_"+HttpRequestUtil.getIpAdrress(request));
        //清除shiro信息
        SecurityUtils.getSubject().logout();
    }
}
